#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "toolkit.h"
#include "DEV/partition/partition.h"
#include "test_getpiece_query.h"
#include "config.h"

#include <pthread.h>

//#include "download_pieces_test.h"
#include "getpieces.h"

void error(){
   fprintf(stderr, "ERROR ");
   pthread_exit(NULL);
}



#ifdef TEST

struct file filetest = {"mana.c", LEECH, 10240, 10, "abcdefghijklmnopqrstuvwxyz123456",0,NULL};

void error(){
   fprintf(stderr,"ERROR");
   exit(1);
}
#endif

struct file * get_file_from_id(int i);

void process_piece(struct  file * f, size_t pieceno, char* buf){
   size_t nbpieces = (f->size / f->piece_size) + ((f->size%(f->piece_size) != 0)?1:0);
   fprintf(stderr,"\n%d %d %d %d\n",f->size,f->piece_size,nbpieces,pieceno);
   if(pieceno >= nbpieces)
      fprintf(stderr,"ERROR le pair a envoyé une pièce de nro trop grand.");

   int piece_size;
   if(pieceno == nbpieces - 1)
      piece_size = f->size % f->piece_size ;
   else
      piece_size = f->piece_size;

   recompose_file(f->name, pieceno, buf, piece_size);
}






void * download_pieces (struct down_args * argum){
   /************************************************************/
   /*  Envoi de la requête
    */

#ifndef TEST

   char query[GP_QUERY_SIZE];
   getpieces_query(query, argum->gp_file, argum->bm);

   int sockfd  = open_connect(argum->cl->IP, argum->cl->port);

   int wt = write(sockfd, query, strlen(query)); //FIXME: faire une boucle

#else
   int sockfd  = open_connect(TESTIP, TESTPORT);
#endif



   /***********************************************************/
   /*  Réception de la requête
    */

#ifndef TEST
   struct file * f = get_file_from_id(argum->gp_file);
#else
   struct file * f = &filetest;
#endif

   char * res = malloc(f->piece_size + 10);      //buffer d'arrivée
   size_t i = 0;                                //curseur
   char buf_num_piece[10];                      

   char * buf_piece = malloc(f->piece_size);


   read(sockfd, res, 4+1+32+1+1); //"data $key [" 


#define CMP_CUR(base,cur,str) {size_t _size_ = strlen(str); \
   if(strncmp(base+cur,str,_size_) != 0) \
         error();                    \
   cur+= _size_;}


   i=0;
   printf("->%.39s \n",res);

   CMP_CUR(res,i,"data ");

   i+=32; //ignore key

   CMP_CUR(res,i," [");


   /* Lecture du numéro de pièce + potentiellement
    * le début de la pièce
    */
   while(1){
      bzero(buf_num_piece,sizeof buf_num_piece);
      bzero(buf_piece,sizeof buf_piece);

      read(sockfd, res, 6); 
#ifdef TEST
      printf("##%.6s \n",res);
#endif

      if(res[0] == ']')
	 break;

      for(i=0; i<6; i++){
	 if(res[i] == ':')
	    break;
	 if(! isdigit(res[i]))
	    error();
	 buf_num_piece[i] = res[i];
      }
      i++;
      buf_num_piece[i] = '\0';

      size_t piece_number = atoi(buf_num_piece);
#ifdef TEST
      fprintf(stderr,"%s\n",buf_num_piece);
#endif

      int j; //curseur du buffer de piece
      for(j=0; i<6; i++,j++)
	 buf_piece[j] = res[i];
      //j<6 ici

      recv(sockfd,res,f->piece_size - j+1,MSG_WAITALL);

      memcpy(buf_piece+j, res, f->piece_size - j);

#ifdef TEST
      fprintf(stderr,"==%.10s\n",buf_piece);
#endif

      /*Traitement de la pièce*/
      process_piece(f,piece_number,buf_piece);

      if(res[f->piece_size-j] == ']')
	 break;
   }

   argum->cl->downloading = 0;
   pthread_mutex_unlock(&argum->cl->mutex);

   close(sockfd);
   return NULL; //don't care

}


#ifdef TEST
int main(){
   download_pieces(NULL);
}
#endif
